package com.geovis.emergency.spd.biz.pc.service.impl;


import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.IterUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.geovis.common.core.constant.CommonConstants;
import com.geovis.emergency.spd.biz.basic.service.IBasicDutyOrgService;
import com.geovis.emergency.spd.biz.iflytek.thread.PushThread;
import com.geovis.emergency.spd.biz.pc.mapper.PcPlanMapper;
import com.geovis.emergency.spd.biz.pc.mapper.PcPlanOrgUserMapper;
import com.geovis.emergency.spd.biz.pc.service.*;
import com.geovis.emergency.spd.biz.system.service.ISystemFileService;
import com.geovis.emergency.spd.biz.system.service.ISystemUserService;
import com.geovis.emergency.spd.biz.system.wrapper.ForestNodeMerger;
import com.geovis.emergency.spd.cache.DeptCache;
import com.geovis.emergency.spd.cache.DictCache;
import com.geovis.emergency.spd.cache.RegionCache;
import com.geovis.emergency.spd.cache.SysCache;
import com.geovis.emergency.spd.entity.basic.pojo.dto.BasicDutyOrgTreeDTO;
import com.geovis.emergency.spd.entity.basic.pojo.vo.BasicDutyOrgVO;
import com.geovis.emergency.spd.entity.pc.entity.*;
import com.geovis.emergency.spd.entity.pc.pojo.constant.PcDisasterConstant;
import com.geovis.emergency.spd.entity.pc.pojo.constant.PcDrillConstant;
import com.geovis.emergency.spd.entity.pc.pojo.constant.PcPlanConstant;
import com.geovis.emergency.spd.entity.pc.pojo.dto.PcPlanQueryDTO;
import com.geovis.emergency.spd.entity.pc.pojo.dto.PcPlanSaveDTO;
import com.geovis.emergency.spd.entity.pc.pojo.dto.PcPlanUpdateDTO;
import com.geovis.emergency.spd.entity.pc.pojo.enums.StatusEnum;
import com.geovis.emergency.spd.entity.pc.pojo.vo.PcPlanDetailVO;
import com.geovis.emergency.spd.entity.pc.pojo.vo.PcPlanDutyOrgDeptVO;
import com.geovis.emergency.spd.entity.pc.pojo.vo.PcPlanDutyOrgVO;
import com.geovis.emergency.spd.entity.system.constant.SystemFileBusinessConstant;
import com.geovis.emergency.spd.entity.system.entity.SystemDept;
import com.geovis.emergency.spd.entity.system.entity.SystemFile;
import com.geovis.emergency.spd.entity.system.entity.SystemRegion;
import com.geovis.emergency.spd.entity.system.entity.SystemUser;
import com.geovis.emergency.spd.entity.system.pojo.dto.SystemFileDTO;
import com.geovis.emergency.spd.entity.system.pojo.dto.SystemFileQueryDTO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.lang.reflect.Array;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 应急预案指挥模块 - 预案管理 服务实现类
 * </p>
 *
 * @author Lonsho
 * @since 2022-06-17
*/

@Service
@RequiredArgsConstructor
@Slf4j
public class PcPlanServiceImpl extends ServiceImpl<PcPlanMapper, PcPlan> implements IPcPlanService {

    private final IPcPlanDutyDeptService pcPlanDutyDeptService;
    private final IPcPlanDutyOrgService pcPlanDutyOrgService;
    private final IPcPlanDutyOrgDeptService pcPlanDutyOrgDeptService;
    private final ISystemFileService systemFileService;
    private final IBasicDutyOrgService basicDutyOrgService;
    private final PcPlanOrgUserMapper pcPlanOrgUserMapper;
    private final IPcDisasterService pcDisasterService;
    private final ISystemUserService systemUserService;

    private final IPcPlanStructureService pcPlanStructureService;

    private void savePlanStructure(List<PcPlanStructure> structures,String planId)
    {
        //过滤掉一些没填内容的类型
        List<PcPlanStructure> saveEntity=structures.stream().filter(s-> StringUtils.hasText(s.getContent())).collect(Collectors.toList());
        if(!CollectionUtils.isEmpty(saveEntity))
        {
            saveEntity.stream().forEach(s->{
                s.setPcPlanId(planId);
            });
            pcPlanStructureService.saveBatch(saveEntity);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void savePcPlan(PcPlanSaveDTO saveDTO) {
        //保存预案基础信息
        PcPlan pcPlan=new PcPlan();
        BeanUtil.copyProperties(saveDTO,pcPlan);
        baseMapper.insert(pcPlan);
        String planId=pcPlan.getId();

        //保存结构化数据
        if(!CollectionUtils.isEmpty(saveDTO.getStructures()))
        {
            savePlanStructure(saveDTO.getStructures(),planId);
        }

        //保存附件
        systemFileService.linkBusiness(saveDTO.getPlaningFileList(), pcPlan.getId(), SystemFileBusinessConstant.TYPE_PLAN_PLANING);
        systemFileService.linkBusiness(saveDTO.getManualWorkFileList(), pcPlan.getId(), SystemFileBusinessConstant.TYPE_PLAN_MANUAL_WORK);
        systemFileService.linkBusiness(saveDTO.getWorkRulesFileList(), pcPlan.getId(), SystemFileBusinessConstant.TYPE_PLAN_WORK_RULES);
        systemFileService.linkBusiness(saveDTO.getOperationManualFileList(), pcPlan.getId(), SystemFileBusinessConstant.TYPE_PLAN_OPERATION_MANUAL);
        systemFileService.linkBusiness(saveDTO.getOverViewFileList(), pcPlan.getId(), SystemFileBusinessConstant.TYPE_PLAN_OVERVIEW);
        systemFileService.linkBusiness(saveDTO.getOtherFileList(), pcPlan.getId(), SystemFileBusinessConstant.TYPE_PLAN_OTHER);

        //保存组织架构已经成员单位关联信息
        pcPlanDutyOrgService.savePlanDutyOrg(saveDTO.getDutyOrgList(),pcPlan.getId(),null,null);


    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updatePcPlan(PcPlanUpdateDTO pcPlanUpdateDTO) {
        PcPlan pcPlan= baseMapper.selectById(pcPlanUpdateDTO.getId());
        BeanUtil.copyProperties(pcPlanUpdateDTO,pcPlan);
        baseMapper.updateById(pcPlan);
        //先删除结构化数据，如果前端不传数据，则表示清空结构化数据
        pcPlanStructureService.remove(Wrappers.lambdaQuery(PcPlanStructure.class)
                .eq(PcPlanStructure::getPcPlanId, pcPlan.getId()));
        //保存结构化数据
        if(!CollectionUtils.isEmpty(pcPlanUpdateDTO.getStructures()))
        {
            savePlanStructure(pcPlanUpdateDTO.getStructures(),pcPlan.getId());
        }

        //保存附件
        systemFileService.linkBusiness(pcPlanUpdateDTO.getPlaningFileList(), pcPlan.getId(), SystemFileBusinessConstant.TYPE_PLAN_PLANING);
        systemFileService.linkBusiness(pcPlanUpdateDTO.getManualWorkFileList(), pcPlan.getId(), SystemFileBusinessConstant.TYPE_PLAN_MANUAL_WORK);
        systemFileService.linkBusiness(pcPlanUpdateDTO.getWorkRulesFileList(), pcPlan.getId(), SystemFileBusinessConstant.TYPE_PLAN_WORK_RULES);
        systemFileService.linkBusiness(pcPlanUpdateDTO.getOperationManualFileList(), pcPlan.getId(), SystemFileBusinessConstant.TYPE_PLAN_OPERATION_MANUAL);
        systemFileService.linkBusiness(pcPlanUpdateDTO.getOverViewFileList(), pcPlan.getId(), SystemFileBusinessConstant.TYPE_PLAN_OVERVIEW);
        systemFileService.linkBusiness(pcPlanUpdateDTO.getOtherFileList(), pcPlan.getId(), SystemFileBusinessConstant.TYPE_PLAN_OTHER);

        //保存组织架构已经成员单位关联信息
        //先删除关联数据
        if(!CollectionUtils.isEmpty(pcPlanUpdateDTO.getDutyOrgList()))
        {
            //先删除数据
            pcPlanDutyOrgService.removeDutyOrg(pcPlanUpdateDTO.getDutyOrgList(),pcPlan.getId());
            pcPlanOrgUserMapper.delete(Wrappers.lambdaQuery(PcPlanOrgUser.class)
                    .eq(PcPlanOrgUser::getPcPlanId, pcPlanUpdateDTO.getId()));
            pcPlanDutyOrgService.savePlanDutyOrg(pcPlanUpdateDTO.getDutyOrgList(),pcPlan.getId(),null,null);
        }
    }
    public PcPlanDetailVO detailVO(String pcPlanId){
        PcPlanDetailVO pcPlanDetail = new PcPlanDetailVO();
        if (StrUtil.isNotBlank(pcPlanId)){
            PcPlan pcPlan = baseMapper.selectById(pcPlanId);
            BeanUtil.copyProperties(pcPlan,pcPlanDetail);

            if (StrUtil.isNotBlank(pcPlan.getType())){
                String dictValue = DictCache.getDictValue(PcDisasterConstant.DISASTER_TYPE, pcPlan.getType());
                pcPlanDetail.setTypeName(dictValue);
            }
            if (StrUtil.isNotBlank(pcPlan.getRegionCode())){
                SystemRegion systemRegion = RegionCache.getByCode(pcPlan.getRegionCode());
                if (ObjectUtil.isNotNull(systemRegion)){
                    pcPlanDetail.setRegionName(systemRegion.getName());
                }
            }
            //附件
            pcPlanDetail.setPlaningFileList(getFileList(pcPlanId,SystemFileBusinessConstant.TYPE_PLAN_PLANING));
            pcPlanDetail.setManualWorkFileList(getFileList(pcPlanId,SystemFileBusinessConstant.TYPE_PLAN_MANUAL_WORK));
            pcPlanDetail.setWorkRulesFileList(getFileList(pcPlanId,SystemFileBusinessConstant.TYPE_PLAN_WORK_RULES));
            pcPlanDetail.setOperationManualFileList(getFileList(pcPlanId,SystemFileBusinessConstant.TYPE_PLAN_OPERATION_MANUAL));
            pcPlanDetail.setOverViewFileList(getFileList(pcPlanId,SystemFileBusinessConstant.TYPE_PLAN_OVERVIEW));
            pcPlanDetail.setOtherFileList(getFileList(pcPlanId,SystemFileBusinessConstant.TYPE_PLAN_OTHER));
            //设置组织架构与人员
            pcPlanDetail.setDutyOrgList(getSelectedOrgUsers(pcPlanId));
            //预案结构化
            List<PcPlanStructure> structures=pcPlanStructureService.list(Wrappers.lambdaQuery(PcPlanStructure.class)
                    .eq(PcPlanStructure::getPcPlanId, pcPlan.getId()));
            pcPlanDetail.setStructures(structures);

        }
        //组织架构为空，使用基础组织架构
        if (CollUtil.isEmpty(pcPlanDetail.getDutyOrgList())){
            List<BasicDutyOrgVO> basicDutyOrgList = basicDutyOrgService.selectList(new BasicDutyOrgTreeDTO());
            List<PcPlanDutyOrgVO> collect = basicDutyOrgList.stream()
                    .map(basicDutyOrgVO -> BeanUtil.toBean(basicDutyOrgVO, PcPlanDutyOrgVO.class))
                    .collect(Collectors.toList());
            pcPlanDetail.setDutyOrgList(ForestNodeMerger.merge(collect));
        }



        return pcPlanDetail;
    }

    private List<PcPlanDutyOrgVO> getSelectedOrgUsers(String pcPlanId)
    {
        //组织架构
        List<PcPlanDutyOrg> dutyOrgList = pcPlanDutyOrgService.list(
                Wrappers.lambdaQuery(PcPlanDutyOrg.class)
                        .eq(PcPlanDutyOrg::getPcPlanId, pcPlanId)
                        .orderByDesc(PcPlanDutyOrg::getParentId)
                        .orderByAsc(PcPlanDutyOrg::getIdx)
        );
        //勾选的人员
        List<PcPlanOrgUser> planOrgUsers = pcPlanOrgUserMapper.selectList(
                Wrappers.lambdaQuery(PcPlanOrgUser.class)
                        .eq(PcPlanOrgUser::getPcPlanId, pcPlanId)
        );

        //组织架构不为空
        if (ObjectUtil.isNotEmpty(dutyOrgList)){
            List<PcPlanDutyOrgVO> collect = dutyOrgList.stream()
                    .map(basicDutyOrgVO -> {
                        //选中的人员
                        PcPlanDutyOrgVO pcPlanDutyOrg = BeanUtil.toBean(basicDutyOrgVO, PcPlanDutyOrgVO.class);
                        List<PcPlanOrgUser> users = planOrgUsers.stream()
                                .filter(s -> pcPlanDutyOrg.getId().equals(s.getPcPlanOrgId()))
                                .collect(Collectors.toList());
                        pcPlanDutyOrg.setDutyOrgDeptList(users);
                        return pcPlanDutyOrg;
                    })
                    .collect(Collectors.toList());
            return ForestNodeMerger.merge(collect);
        }
        return null;
    }

    private List<SystemFile> getFileList(String relatedId,String type){
        //获取附件信息
        List<SystemFile> list = systemFileService.getListById(relatedId,type);
        list.sort(Comparator.comparing(SystemFile::getCreateTime));
        return list;
    }
    public LambdaQueryWrapper<PcPlan> getWrapper(PcPlanQueryDTO queryDTO) {
        //创建查询条件
        LambdaQueryWrapper<PcPlan> wrapper = Wrappers.lambdaQuery(PcPlan.class).orderByDesc(PcPlan::getCreateTime);
        if (ObjectUtil.isNotEmpty(queryDTO)) {
            wrapper.like(ObjectUtil.isNotEmpty(queryDTO.getTitle()), PcPlan::getTitle, queryDTO.getTitle())
                    .in(CollUtil.isNotEmpty(queryDTO.getTypeList()), PcPlan::getType, queryDTO.getTypeList())
                    .eq(ObjectUtil.isNotEmpty(queryDTO.getType()), PcPlan::getType, queryDTO.getType())
                    .eq(ObjectUtil.isNotEmpty(queryDTO.getDataStatus()), PcPlan::getDataStatus, queryDTO.getDataStatus());
        }
        return wrapper;
    }

    @Override
    public boolean hasRelatedDisaster(Set<String> idList) {
        LambdaQueryWrapper<PcDisaster> wrapper = Wrappers.lambdaQuery(PcDisaster.class).in(PcDisaster::getPcPlanId,idList).eq(PcDisaster::getDataStatus,"1").eq(PcDisaster::getIsDeleted, "0");
        List<PcDisaster> list=pcDisasterService.list(wrapper);
        return !CollectionUtils.isEmpty(list);
    }

    @Override
    public String checkPlanExistUsers(Set<String> userIds) {
        List<PcPlan> pcPlans=this.list(Wrappers.lambdaUpdate(PcPlan.class)
                .eq(PcPlan::getDataStatus, StatusEnum.TRUE.getCode())
        );
        if(CollectionUtils.isEmpty(pcPlans))
        {
            return null;
        }
//        List<PcDrill> doingDrills=drills.stream().filter(d->PcDrillConstant.STATUS_DOING.equals(d.getStatus())).collect(Collectors.toList());
        List<SystemUser> users=systemUserService.listByIds(userIds);
        Map<String, SystemUser> systemUserMap = IterUtil.toMap(users, SystemUser::getId);
        List<String> planIds=pcPlans.stream().map(PcPlan::getId).collect(Collectors.toList());
        List<PcPlanOrgUser> planUers=pcPlanOrgUserMapper.selectList(Wrappers.lambdaUpdate(PcPlanOrgUser.class)
                .in(PcPlanOrgUser::getPcPlanId,planIds)
        );
        if(CollectionUtils.isEmpty(planUers))
        {
            return null;
        }
        //校验结果集合
        List<String> resultMsg=new ArrayList<>();
        userIds.stream().forEach(userId->{
            //不合格的方案id集合
            List<String> errorPlanIds=planUers.stream().filter(p->p.getPrincipalIds().contains(userId)).map(PcPlanOrgUser::getPcPlanId).distinct().collect(Collectors.toList());
            if(!CollectionUtils.isEmpty(errorPlanIds))
            {
                List<String> errorTitles=pcPlans.stream().filter(p->errorPlanIds.contains(p.getId())).map(PcPlan::getTitle).collect(Collectors.toList());
                SystemUser user=systemUserMap.get(userId);
                String msg="用户【"+user.getRealName()+"】"+"在这些预案中【"+String.join(",",errorTitles)+"】已被设置，请先移除用户或删除预案";
                resultMsg.add(msg);
            }

        });
        if(!CollectionUtils.isEmpty(resultMsg))
        {
            return String.join(";",resultMsg);
        }
        return null;
    }

    @Override
    public Boolean checkInDisaster(List<String> ids,Boolean containStopDisaster) {
        List<String> status= new ArrayList<>();
        status.add(CommonConstants.YES);
        if(containStopDisaster)
        {
            status.add(CommonConstants.NO);
        }
        //注意测试下灾害事件被删除的情况
        List<PcDisaster> disasters=pcDisasterService.list(Wrappers.lambdaQuery(PcDisaster.class).in(PcDisaster::getPcPlanId,ids).in(PcDisaster::getDataStatus,status));
        if(!CollectionUtils.isEmpty(disasters))
        {
            return true;
        }

        return false;
    }
}
